/*
   Copyright 2010 Johan Hilding

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

package org.johanhil.flygtider;

import java.io.Serializable;
import java.util.List;

import org.johanhil.flygtider.flightwatch.FlightWatcher;
import org.johanhil.flygtider.provider.FetchFlights;
import org.johanhil.flygtider.provider.FlightInfo;
import org.johanhil.flygtider.ui.EndOfListReachedListener;
import org.johanhil.flygtider.ui.FlightInfoAdapter;
import org.johanhil.flygtider.ui.FlightListItemClickHandler;

import android.app.Activity;
import android.app.Dialog;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

/**
 * This is the activity that lists all the flights arriving/departing at an
 * airport.
 * 
 * TODO: * A "Get more flights" list footer, like STHLM Traveling does with its
 * arrow. * Make the same fetch keep on trucking when the phone is turned (and a
 * new activity is created)
 */
public class FlightListActivity extends ListActivity implements EndOfListReachedListener
{
    List<FlightInfo> flights;
    FetchFlights fetchFlightsTask;
    FlightWatcher flightWatcher;
    String airport;
    Boolean arriving;
    String keyword;
    int page = 1;
    int style = FlightInfoAdapter.SIMPLE;
    private FlightListItemClickHandler flightListItemClickHandler;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        final Intent intent = getIntent();
        final String queryAction = intent.getAction();
        Bundle extras;
        
        if (Intent.ACTION_SEARCH.equals(queryAction)) {
            keyword = intent.getStringExtra(SearchManager.QUERY);
            style = FlightInfoAdapter.DETAILED;
        }

        if (keyword == null && intent.getExtras() == null)
        {
            // if we got here not by searching and there were no extras provided...
            // send back to the search activity. (lol error handling)
            finish();
        }

        if (keyword != null)
        {
            extras = intent.getBundleExtra(SearchManager.APP_DATA);
        }
        else
        {
            extras = intent.getExtras();
        }
        
        airport = extras.getString("airport");
        arriving = extras.getBoolean("arriving");

        // do we have a list of flights already?
        // TODO this should be a non configuration retain instance bla bla (getLastNonConfigurationInstance)
        if (savedInstanceState != null && savedInstanceState.containsKey("flights"))
        {
            flights = (List<FlightInfo>) savedInstanceState.get("flights");
            FlightListActivity.this.setListAdapter(new FlightInfoAdapter(
                    FlightListActivity.this,
                    R.layout.flightinfoitem,
                    style, flights));
        }
        else
        {
            fetchFlights();
        }
        
        flightWatcher = new FlightWatcher(getApplicationContext());
        
        setupListeners();
    }

    public boolean onCreateOptionsMenu(Menu menu)
    {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.flightlistactivity_options, menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item)
    {
        // this is very wrong, but I've forgotten how to do it properly :<
        if ("Sök".equals(item.getTitle()))
        {
            onSearchRequested();
        }
        else
        {
            fetchFlights();
            setupListeners();
        }

        return true;
    }
    
    public void onSaveInstanceState(Bundle outBundle)
    {
        if (flights != null)
        {
            outBundle.putSerializable("flights", (Serializable) flights);
        }   
    }
    
    @Override
    public boolean onSearchRequested() {
        Bundle appData = new Bundle();
        appData.putString("airport", airport);
        appData.putBoolean("arriving", arriving);
        startSearch(null, false, appData, false);
        return true;
    }
    
    private void setupListeners()
    {
        flightListItemClickHandler = new FlightListItemClickHandler(this,
                flightWatcher, flights, false);

        this.getListView().setOnItemClickListener(flightListItemClickHandler);
        this.getListView().setOnCreateContextMenuListener(
                flightListItemClickHandler);
    }
    
    private void fetchFlights()
    {
        fetchFlightsTask = new FetchFlights(this, R.string.loading_flights,
                new FetchFlights.ResultHandler()
        {
            public void handleResult(List<FlightInfo> result)
            {
                flights = result;
                
                if (result == null || result.size() == 0)
                {
                    Toast.makeText(FlightListActivity.this, "Kunde inte ansluta till servern. Försök igen senare!", Toast.LENGTH_LONG).show();
                    finish();
                }
                
                FlightListActivity.this.setListAdapter(new FlightInfoAdapter(
                        FlightListActivity.this,
                        R.layout.flightinfoitem,
                        style, result));
                setupListeners();

            }
        });

        // aaand execute
        if (keyword != null)
            fetchFlightsTask.execute(airport, arriving, keyword);
        else
            fetchFlightsTask.execute(airport, arriving);
    }

    private class SearchDialogHandler implements View.OnClickListener
    {
        private Dialog dialog;
        private Activity activity;

        public SearchDialogHandler(Activity activity, Dialog dialog)
        {
            this.activity = activity;
            this.dialog = dialog;
        }

        @Override
        public void onClick(View v)
        {
            EditText input = (EditText) dialog.findViewById(R.id.keyword);
            String keyword = ((Editable) input.getText()).toString();

            dialog.dismiss();
            fetchFlightsTask = new FetchFlights(activity,
                    R.string.loading_flights, new FetchFlights.ResultHandler()
                    {
                        public void handleResult(List<FlightInfo> result)
                        {
                            setListAdapter(new FlightInfoAdapter(activity,
                                    R.layout.flightinfoitem,
                                    FlightInfoAdapter.DETAILED, flights));
                            setupListeners();

                        }
                    });
            fetchFlightsTask.execute(airport, arriving, keyword);
        }
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        flightWatcher.close();
    }

    @Override
    public void endOfListReached()
    {
        if (this.getListView().getCount() == page*30) // did we have more flights?
        {
            // fetch more flights
            fetchFlightsTask = new FetchFlights(this,
                    R.string.loading_flights, new FetchFlights.ResultHandler()
            {
                public void handleResult(List<FlightInfo> result)
                {
                    setListAdapter(new FlightInfoAdapter(FlightListActivity.this,
                            R.layout.flightinfoitem,
                            FlightInfoAdapter.DETAILED, flights));
                    setupListeners();

                }
            });
            
            fetchFlightsTask.execute(airport, arriving, keyword, page);
            page++;
        }
    }
}
